package cn.stylefeng.mferp.socketio;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
//import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
//import com.liyisoft.pay4another.channel.entity.PayBankInfo;
//import com.liyisoft.pay4another.channel.entity.PayOrderInfo;
//import com.liyisoft.pay4another.channel.service.IPayBankInfoService;
//import com.liyisoft.pay4another.channel.service.IPayOrderInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author hxy
 */
@Service(value = "socketIOService")
public class SocketIOServiceImpl implements SocketIOService {
    private static final Logger LOG = LoggerFactory.getLogger(SocketIOServiceImpl.class);

    /**
     * 用来存已连接的客户端
     */
    private static Map<String, SocketIOClient> clientMap = new ConcurrentHashMap<>();

    @Autowired
    private SocketIOServer socketIOServer;

    /**
     * Spring IoC容器创建之后，在加载SocketIOServiceImpl Bean之后启动
     *
     * @throws Exception
     */
    //@PostConstruct
    private void autoStartup() throws Exception {
        start();
    }

    /**
     * Spring IoC容器在销毁SocketIOServiceImpl Bean之前关闭,避免重启项目服务端口占用问题
     *
     * @throws Exception
     */
    //@PreDestroy
    private void autoStop() throws Exception {
        stop();
    }

    @Override
    public void start() {
        // 监听客户端连接
        socketIOServer.addConnectListener(client -> {
            String loginUserNum = getParamsByClient(client);
            if (loginUserNum != null) {
                PushMessage pushMessage = new PushMessage();
                // 查询卡号是否存在
                /*PayBankInfo appBankInfo = payBankInfoService.getById(loginUserNum);*/
                // 卡号不存在，返回错误
                /*if (null == appBankInfo) {
                    pushMessage.setContent("卡号不存在，或未启用");
                    client.sendEvent(PUSH_EVENT, pushMessage);
                    client.disconnect();
                    return;
                }*/

                SocketIOClient oldClient = clientMap.get(loginUserNum);
                // 卡号被登录，提示并断开连接
                if (null == oldClient) {
                    clientMap.put(loginUserNum, client);
                    // 更新转账状态为 0 等待
                    // appBankInfo.setAppPayStatus("0");
                } else {
                    clientMap.remove(loginUserNum);
                    oldClient.disconnect();
                    clientMap.put(loginUserNum, client);
                    // appBankInfo.setAppPayStatus("0");
                }
                // 判断如果有处理中的订单，则继续处理
                /*QueryWrapper<PayOrderInfo> payOrderInfoQueryWrapper = new QueryWrapper<>();
                payOrderInfoQueryWrapper.eq("status", "1").eq("app_bank_card", loginUserNum);
                PayOrderInfo channelOrder = payOrderInfoService.getOne(payOrderInfoQueryWrapper, false);
                if (null != channelOrder) {
                    appBankInfo.setAppPayStatus("1");
                    try {
                        Thread.sleep(1000);
                        this.pushMessageToUser(appBankInfo.getAppCardNumber(), JSON.toJSONString(channelOrder), SocketIOService.GET_ORDER);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                payBankInfoService.updateById(appBankInfo);*/
            } else {
                client.disconnect();
            }
        });
        // 监听客户端断开连接
        socketIOServer.addDisconnectListener(client -> {
            String loginUserNum = getParamsByClient(client);
            if (loginUserNum != null) {
                // 查询卡号是否存在
                /*PayBankInfo appBankInfo = payBankInfoService.getById(loginUserNum);
                if (null != appBankInfo) {
                    appBankInfo.setAppPayStatus("2");
                    payBankInfoService.updateById(appBankInfo);
                }*/
                // 状态更新为2，断开连接
                clientMap.remove(loginUserNum);
                client.disconnect();
            }
        });

        // 处理自定义的事件，与连接监听类似
        socketIOServer.addEventListener(PUSH_EVENT, PushMessage.class, (client, data, ackSender) -> {
            // TODO do something
            // 前端传回消息
            System.out.println(data.getContent() + "---" + data.getLoginUserNum());

        });

        // 处理自定义的事件，与连接监听类似
        socketIOServer.addEventListener(TRANSFER_SUCCESS, JSONObject.class, (client, data, ackSender) -> {
            // 前端传回消息
            System.out.println(data.toJSONString());

            /*if (null == channelOrder) {
                client.sendEvent(TRANSFER_SUCCESS, "交易失败,订单不存！");
                return;
            }*/
        });

        // 处理自定义的事件，与连接监听类似
        socketIOServer.addEventListener(TRANSFER_FAIL, JSONObject.class, (client, data, ackSender) -> {
            // 根据客户端银行卡号 和 订单编号 以及订单当前状态更新订单
            // 前端传回消息
            System.out.println(data.toJSONString());
            client.sendEvent(TRANSFER_FAIL, "交易失败！");
        });

        socketIOServer.addEventListener(GET_ORDER, String.class, (client, data, ackSender) -> {
            // 根据客户端银行卡号 和 订单编号 以及订单当前状态更新订单
//            JSONObject result = JSON.parseObject(data);
            // TODO do something
            // 前端传回消息
            System.out.println(data);

        });
        socketIOServer.addEventListener(GET_ORDER, String.class, (client, data, ackSender) -> {
            // 根据客户端银行卡号 和 订单编号 以及订单当前状态更新订单
//            JSONObject result = JSON.parseObject(data);
            // TODO do something
            // 前端传回消息
            System.out.println(data);

        });
        socketIOServer.start();
    }

    @Override
    public void stop() {
        if (socketIOServer != null) {
            socketIOServer.stop();
            socketIOServer = null;
        }
    }

    /**
     * 断开连接
     *
     * @param loginUserNum
     */
    @Override
    public void disconnect(String loginUserNum) {
        SocketIOClient client = clientMap.get(loginUserNum);
        if (client != null) {
            client.disconnect();
        }
    }

    @Override
    public void pushMessageToUser(PushMessage pushMessage) {
        String loginUserNum = pushMessage.getLoginUserNum().toString();
        SocketIOClient client = clientMap.get(loginUserNum);
        if (client != null) {
            client.sendEvent(PUSH_EVENT, pushMessage);
        }
    }

    @Override
    public void pushMessageToUser(String loginUserNum, String content, String event) {
        LOG.info("推送用户：" + loginUserNum);
        SocketIOClient client = clientMap.get(loginUserNum);
        if (client != null) {
            client.sendEvent(event, content);
        }
        LOG.info("socket断开：" + loginUserNum);
    }

    /**
     * 此方法为获取client连接中的参数，可根据需求更改
     *
     * @param client
     * @return
     */
    private String getParamsByClient(SocketIOClient client) {
        // 从请求的连接中拿出参数（这里的loginUserNum必须是唯一标识）
        Map<String, List<String>> params = client.getHandshakeData().getUrlParams();
        List<String> list = params.get("loginUserNum");
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 获取当前列表
     * @return
     */
    @Override
    public Map<String, SocketIOClient> getMaps(){
        return clientMap;
    }
}